/* 
 *  Created By: Tom Shirley
 *  Project URL: http://www.codeplex.com/accesschecker
 *  License: GNU GPL v2
 *  Copyright (C) 2008 Tom Shirley
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 */
using System;
using System.Web;
using System.Text;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Resources;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Utilities;
using arb.Generic.SharedLibrary.exceptionHandling;

namespace AccessChecker2010
{
    /// <summary>
    ///Quickly check what objects within a Sharepoint site hierarchy a user has access to. 
    ///
    ///The Access Checker Web Part is a .net 2.0 web part used within Windows Sharepoint Services v3 and/or Micorosoft Office Sharepoint Server 2007, 
    /// to display a tree view depicting permissions on securable objects for a user scoped to a Site hierarchy.
    ///
    ///More specifically, you can view graphically whether a user has a particular set of permissions on Sites and 
    /// Lists. Nodes within the tree view are colour coded to allow fast recognition of what Sites and Lists a user
    /// has access to, providing a site administrator the ability to answer the often raised question, 
    /// "do i have access to everything on this site?" 
    ///
    ///Without this web part there is no fast way for a site admin to determine if a user has access to all lists 
    /// and all sub-sites within a Site.
    ///
    ///Additional Features
    ///- View Permission Inheritance on Sites and Lists. Useful for site administrators to understand the 
    /// permissioning on their sites.
    ///
    ///Limitations
    ///- Folders/List Items are not displayed.
    /// </summary>
    
    [SupportsAttributeMarkup(true)]
    public partial class AccessCheckerWebPart : BaseWebPart<AccessCheckerEditorPart>
    {
        #region Properties

        private string _ErrorMessage = string.Empty;
        private SPWeb _CurrentWeb;
        private SPSite _CurrentSite;
        private AccessCheckerInputForm _InputForm;
        private SPPermissionsTreeView _SharepointPermissionsTreeView;
        private Label _MessageArea;

        private SPBasePermissions _BasePermissions;
        private bool _AccessDeniedExceptionSetting;
        private Exception _Exception;
        private bool _DownloadReport;
        private const string DEFAULT_SHOW_USER_OR_WEB_PERMISSONS_VALUE = "User";

        private string _ShowUserOrWebPermissions = DEFAULT_SHOW_USER_OR_WEB_PERMISSONS_VALUE;


        public AccessCheckerInputForm InputForm
        {
            get { return _InputForm; }
        }

        /// <summary>
        /// Gets or sets a property which indicates the type of object to report permissions against.
        /// </summary>
        /// <value>String representation of AccessCheckerMode enumeration element.</value>
        [Browsable(false)]
        [LocalizedWebDisplayName("ShowUserOrWebPermissions")]
        [LocalizedWebDescription("ShowUserOrWebPermissionsDesc")]
        [LocalizedCategory("Configuration")]
        [DefaultValue(DEFAULT_SHOW_USER_OR_WEB_PERMISSONS_VALUE)]
        [WebPartStorage(Storage.Personal)]
        public string ShowUserOrWebPermissions
        {
            get
            {
                if (_ShowUserOrWebPermissions == null)
                    return DEFAULT_SHOW_USER_OR_WEB_PERMISSONS_VALUE;
                else
                    return _ShowUserOrWebPermissions;
            }

            set
            {
                _ShowUserOrWebPermissions = value;    
            }
        }

        private string _treeNodeFilter = TreeNodeFilterState.ShowAll.ToString();

        /// <summary>
        /// Gets or sets a value to specify whether nodes that match the permissions of the current web
        /// should not be rendered.
        /// </summary>
        /// <value>The hide nodes.</value>
        [Browsable(false)]
        [LocalizedWebDisplayName("TreeNodeFilterName")]
        [LocalizedWebDescription("TreeNodeFilterNameDesc")]
        [LocalizedCategory("Configuration")]
        [DefaultValue("")]
        [WebPartStorage(Storage.Personal)]
        public string TreeNodeFilter
        {
            get
            {
                return _treeNodeFilter;
            }
            set
            {
                _treeNodeFilter = value;
            }
        }

        private const bool AUTO_EXPAND_DEFAULT = true;
        private bool _autoExpand = AUTO_EXPAND_DEFAULT;
        /// <summary>
        /// Gets or sets the if nodes are to be auto expanded.
        /// </summary>
        /// <value>The auto expand.</value>
        [Browsable(false)]
        [LocalizedWebDisplayName("AutoExpandName")]
        [LocalizedWebDescription("AutoExpandNameDesc")]
        [LocalizedCategory("Configuration")]
        [DefaultValue(AUTO_EXPAND_DEFAULT)]
        [WebPartStorage(Storage.Personal)]
        public bool AutoExpand
        {
            get
            {
                return _autoExpand;
            }

            set
            {
               _autoExpand = value;
            }
        }

        private const bool DISPLAY_SUBWEBS_DEFAULT = true;
        private bool _DisplaySubWebs = DISPLAY_SUBWEBS_DEFAULT;

        /// <summary>
        /// Gets or sets a value indicating whether subwebs should be displayed in the tree view.
        /// </summary>
        /// <value><c>true</c> if user requires subwebs to be displayed; otherwise, <c>false</c>.</value>
        [Browsable(false)]
        [LocalizedWebDisplayName("DisplaySubWebsName")]
        [LocalizedWebDescription("DisplaySubWebsNameDesc")]
        [LocalizedCategory("Configuration")]
        [DefaultValue(DISPLAY_SUBWEBS_DEFAULT)]
        [WebPartStorage(Storage.Personal)]
        public bool DisplaySubWebs
        {
            get
            {
                return _DisplaySubWebs;
            }

            set
            {
                 _DisplaySubWebs = value;
            }   
        }
        private const bool IGNORE_CREATESSCSITE_PERMISSION_DEFAULT = true;
        private bool _IgnoreCreateSSCSitePermission = IGNORE_CREATESSCSITE_PERMISSION_DEFAULT;

        /// <summary>
        /// 
        /// </summary>
        /// <value></value>
        [Browsable(false)]
        [LocalizedWebDisplayName("CreateSSCSiteName")]
        [LocalizedWebDescription("CreateSSCSiteNamDesc")]
        [LocalizedCategory("Configuration")]
        [DefaultValue(IGNORE_CREATESSCSITE_PERMISSION_DEFAULT)]
        [WebPartStorage(Storage.Personal)]
        public bool IgnoreCreateSSCSitePermission
        {
            get
            {
                return _IgnoreCreateSSCSitePermission;
            }

            set
            {
                _IgnoreCreateSSCSitePermission = value;
            }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="AccessCheckerWebPart"/> class.
        /// </summary>
        public AccessCheckerWebPart()
        {
            _CurrentWeb = SPContext.Current.Web;
            _CurrentSite = SPContext.Current.Site;
        }
        #endregion

        #region Build control functions

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            try
            {
                // Add all child controls: In order they are the Message area, the input form area and the tree view control.
                _MessageArea = new Label();
                _MessageArea.EnableViewState = false;
                Controls.Add(this._MessageArea);

                _InputForm = new AccessCheckerInputForm((SupportedAuthenticationModes)Enum.Parse(typeof(SupportedAuthenticationModes),
                                                        SPSecurity.AuthenticationMode.ToString()), this.Page, this._CurrentWeb, this._CurrentSite);
                // Wireup the button used to build the SPPremissionsTreeView control
                this._InputForm.GenerateTree.Click += new EventHandler(GenerateTreeviewForUserButton_Click); 
                Controls.Add(_InputForm);
                
                _SharepointPermissionsTreeView = new SPPermissionsTreeView(this._CurrentSite.ID, this._CurrentWeb.ID);
                _SharepointPermissionsTreeView.EnableViewState = true;                
                Controls.Add(_SharepointPermissionsTreeView);
            }
            catch (Exception ex)
            {
                _ErrorMessage += string.Format("{0} CreateChildControls:\r\n{1}", Properties.Resources.Error_In, GetErrorMessage(ex));
            }
        }

        /// <summary>
        /// The event handler for the System.Web.UI.Control.PreRender event that occurs immediately before the Web Part is rendered to the Web Part Page it is contained on.
        /// </summary>
        /// <param name="e">A System.EventArgs that contains the event data.</param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            try
            {
                EnsureChildControls();                
                ConfigureControls();
                RegisterClientSideScripts();

                if (_SharepointPermissionsTreeView != null && _SharepointPermissionsTreeView.Nodes.Count > 0)
                    _SharepointPermissionsTreeView.Nodes[0].Expand(); // Always have root node expanded
            }
            catch (Exception ex)
            {
                _ErrorMessage += string.Format("{0} OnPreRender:\r\n{1}", Properties.Resources.Error_In, GetErrorMessage(ex));
            }
        }

        /// <summary>
        /// Build the tree view that displays the Sharepoint structure from the current context web.
        /// </summary>
        /// <returns></returns>
        private void ConfigureTreeViewStyles()
        {
            this._SharepointPermissionsTreeView.CssClass = "ACWP-SharepointTreeView";
            this._SharepointPermissionsTreeView.NodeStyle.CssClass = "ACWP-SharepointTreeViewNodeStyle";
            this._SharepointPermissionsTreeView.HoverNodeStyle.CssClass = "ACWP-SharepointTreeViewHoverNodeStyle";
        }

        /// <summary>
        /// Configure the controls for the web part. This function:
        /// 1. Checks user permission to run this web part.
        /// 2. Updates Input controls from Query String values.
        /// 3. Validates user input values.
        /// 4. Calls BuildTreeView() if all is OK to build the permissions tree view.
        /// </summary>
        private void ConfigureControls()
        {
            bool propertiesAreValid = true;
            TreeNodeFilterState selectedFilterValue;

            // Always re-build tree view if there is no viewstate (no nodes), or the treeview is showing web inheritance
            // as there is no way to force a re-build for the user, whereas if we are showing user permissions
            // then the user can click Go to force a re-build.
            if (ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))
                DeleteAllNodesInTree();

            _InputForm.Mode = (AccessCheckerMode)Enum.Parse(typeof(AccessCheckerMode), this.ShowUserOrWebPermissions); // Set the mode of the input form before using it

            if (_SharepointPermissionsTreeView == null || _SharepointPermissionsTreeView.Nodes.Count == 0)
            {
                try
                {
                    // Stop Sharepoint from catching access denied exception, so this WP can handle them.
                    _AccessDeniedExceptionSetting = SPSecurity.CatchAccessDeniedException;
                    SPSecurity.CatchAccessDeniedException = false;
                    // Check that the current user has the appropriate permissions to use this web part
                    if (_CurrentWeb.DoesUserHavePermissions(SPBasePermissions.EnumeratePermissions))
                    {
                        ProcessQueryStringValues();
                        
                        // Check that the User and AccessLevel user inputs are valid
                        if (this.ShowUserOrWebPermissions.Equals(AccessCheckerMode.User.ToString()))
                        {

                            if (this._InputForm.AccessLevel != null)
                                _BasePermissions = this._InputForm.AccessLevel.BasePermissions;
                            else
                                propertiesAreValid = false;
                            
                            // Remove the CreateSSCSite permission from the role that is to be used
                            // to compare permissions against. The is done because:
                            // If a user copies a permission set within the UI, the CreateSSCSite permission
                            // isn't copied to the new permission group, moreover there is no option on the 
                            // permission level page to select this permission mask. Therefore two seemingly identical 
                            // permission sets (e.g. Read and Read_ Copy) do not show identical results in
                            // this web part (i.e. nodes don't have the same pass/fail colors).                                    
                            if (IgnoreCreateSSCSitePermission)
                                Common.RemoveCreateSSCSitePermissionFromMask(ref _BasePermissions);

                            // Remove UseClientIntegration permission mask when comparing permissions if
                            // authentication method is forms based. 
                            // Reason: UseClientIntegration mask is strangely not included in default permission levels.                                  
                            if (SPSecurity.AuthenticationMode == System.Web.Configuration.AuthenticationMode.Forms)
                                Common.RemoveUseClientIntegrationPermissionFromMask(ref _BasePermissions); 
 
                            if (this._InputForm.User == null)
                                propertiesAreValid = false;
                        }

                        if (propertiesAreValid)
                        {
                            // The selected value in the radio list control takes prescedence over the runtime web part property
                            // stored in TreeNodeFilter.
                            if (this._InputForm.TreeNodeFilterRadioList.SelectedValue == string.Empty)
                            {
                                selectedFilterValue = (TreeNodeFilterState)Enum.Parse(typeof(TreeNodeFilterState), this.TreeNodeFilter);
                            }
                            else
                                selectedFilterValue = (TreeNodeFilterState)Enum.Parse(typeof(TreeNodeFilterState), this._InputForm.TreeNodeFilterRadioList.SelectedValue);

                            if (ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))
                                this._SharepointPermissionsTreeView.GeneratePermissionInheritanceTree(this._DisplaySubWebs,
                                selectedFilterValue);
                            else if (ShowUserOrWebPermissions.Equals(AccessCheckerMode.User.ToString()))
                                this._SharepointPermissionsTreeView.GenerateUserAccessTree(this._DisplaySubWebs,
                                selectedFilterValue, this._InputForm.User, _BasePermissions);

                            ConfigureTreeViewStyles();

                            // Expand All Nodes if user has set AutoExpand property to "Yes"
                            if (this.AutoExpand == true)
                                this._SharepointPermissionsTreeView.ExpandAll();
                            else
                                this._SharepointPermissionsTreeView.CollapseAll();
                        }
                        else
                            _SharepointPermissionsTreeView = null;
                    }
                    else
                    {
                        _MessageArea.Text = Properties.Resources.Do_Not_Have_Permissions;
                    }
                }
                finally
                {
                    SPSecurity.CatchAccessDeniedException = _AccessDeniedExceptionSetting;
                }
            }
            // Refactor Tree Node filter list into its own class
            AccessCheckerInputForm.ConfigureTreeNodeFilterRadioList(this._InputForm.TreeNodeFilterRadioList, this.TreeNodeFilter, (AccessCheckerMode)Enum.Parse(typeof(AccessCheckerMode), this.ShowUserOrWebPermissions));
        }

        /// <summary>
        /// Gets the node filter description to display to the user.
        /// </summary>
        /// <returns></returns>
        private string GetNodeFilterDescription()
        {
            String description = String.Empty;
            bool HideMatchingNodes = false;
            bool HideDifferentNodes = false;

            if (this._InputForm.TreeNodeFilterRadioList.SelectedValue == TreeNodeFilterState.HideMatchingPermissionNodes.ToString())
                HideMatchingNodes = true;
            if (this._InputForm.TreeNodeFilterRadioList.SelectedValue == TreeNodeFilterState.HideDifferentPermissionNodes.ToString())
                HideDifferentNodes = true;

            if (HideMatchingNodes)
            {
                if (this.ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))
                    description = String.Format(Properties.Resources.Web_Filter_Matching_Permission_Nodes_Long_Description);
                else
                {
                    if (this._InputForm.User != null && this._InputForm.AccessLevel != null)
                        description = String.Format(Properties.Resources.User_Filter_Matching_Permission_Nodes_Long_Description, this._InputForm.User.DisplayName, this._InputForm.AccessLevel.Name);
                }
            }
            else if (HideDifferentNodes)
            {
                if (this.ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))
                    description = String.Format(Properties.Resources.Web_Filter_Different_Permission_Nodes_Long_Description);
                else
                {
                    if (this._InputForm.User != null && this._InputForm.AccessLevel != null)
                        description = String.Format(Properties.Resources.User_Filter_Different_Permission_Nodes_Long_Description, this._InputForm.User.DisplayName, this._InputForm.AccessLevel.Name);
                }
            }
            else
            {
                if (this.ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))
                    description = String.Format(Properties.Resources.Web_Show_All_Nodes_Long_Description);
                else
                {
                    if (this._InputForm.User != null && this._InputForm.AccessLevel != null)
                        description = String.Format(Properties.Resources.User_Show_All_Nodes_Long_Description, this._InputForm.User.DisplayName, this._InputForm.AccessLevel.Name);
                }
            }

            return description;
        }
        #endregion

        #region Render control functions

        /// <summary>
        /// Inherited from System.Web.UI.Control.
        /// </summary>
        /// <param name="writer">The HtmlTextWriter object that receives the server control content.</param>
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            EnsureChildControls();

            try
            {
                if (String.IsNullOrEmpty(_ErrorMessage))
                {
                    // _DownloadReport == True indicates that the user wishes to download the report as an xml file.
                    if (_DownloadReport && _SharepointPermissionsTreeView != null)
                    {
                        DownloadAccessCheckerReport(_SharepointPermissionsTreeView, ShowUserOrWebPermissions, this._InputForm.User, this._InputForm.AccessLevel, this._SharepointPermissionsTreeView.TimeGenerated);
                    }
                    else
                    {
                        writer.Write("<table>");
                        writer.Write("<tr><td class=\"ACWP-MessageArea\">");
                        _MessageArea.RenderControl(writer);
                        writer.Write("</td></tr>");
                        writer.Write("</table>");

                        writer.Write("<table>");
                        writer.Write("<tr><td>");
                        this._InputForm.RenderControl(writer);
                        writer.Write("</td></tr>");
                        writer.Write("</table>");

                        if (_SharepointPermissionsTreeView != null && _SharepointPermissionsTreeView.Nodes.Count > 0)
                        {                            
                            RenderNodeDescription(writer);
                            
                            writer.Write("<table>");
                            writer.Write("<tr><td>");
                            _SharepointPermissionsTreeView.RenderControl(writer); // render the treeview
                            writer.Write("</td></tr>");
                            writer.Write("</table>");
                        }
                    }
                }
                else
                {
                    DisplayErrorToUser(_ErrorMessage, writer);
                    SPSecurity.CodeToRunElevated elevatedLogError = new SPSecurity.CodeToRunElevated(ElevatedLogError);
                    SPSecurity.RunWithElevatedPrivileges(elevatedLogError);
                    //LogError(_ErrorMessage); // The current GenericExceptionHandler class logs to assembly dir. This is causing access denied errors. I am yet to determine where/if i should log to file. So for the meantime i am logging to event logs only
                }
            }
            catch (Exception ex)
            {
                DisplayErrorToUser(GetErrorMessage(ex), writer);
                _Exception = ex;
                SPSecurity.CodeToRunElevated elevatedLogError = new SPSecurity.CodeToRunElevated(ElevatedLogError);
                SPSecurity.RunWithElevatedPrivileges(elevatedLogError);
            }
        }

        /// <summary>
        /// Render a description of the tree node coloring to help users understand what the tree view displays.
        /// </summary>
        /// <param name="writer">The writer.</param>
        private void RenderNodeDescription(HtmlTextWriter writer)
        {
            writer.Write("<table class=\"ACWP_NodeDescriptionTable\">");
            writer.Write("<tr><td>");
            writer.Write(GetNodeFilterDescription());
            writer.Write("</td></tr>");
            writer.Write("</table>");
        }

        #endregion

        #region Misc functions
      
        /// <summary>
        /// Processes the query string values. Primarily used to populate input values via query strings
        /// for the purpose of downloading a report.
        /// </summary>
        private void ProcessQueryStringValues()
        {
            bool allQSValuesValidForUserMode = true;
            string value;
            
            if (this.Page.Request.QueryString.Count > 0)
            {
                try
                {
                    if (this.Page.Request.QueryString["Mode"] != null)
                    {
                        value = HttpUtility.UrlDecode(this.Page.Request.QueryString["Mode"]);
                        if (Enum.IsDefined(typeof(AccessCheckerMode), value))
                        {
                            ShowUserOrWebPermissions = Enum.Parse(typeof(AccessCheckerMode), value, true).ToString();
                        }
                        else
                            throw new ApplicationException(Properties.Resources.Query_String_Invalid);
                    }
                    else
                        allQSValuesValidForUserMode = false;

                    if (this.Page.Request.QueryString["Login"] != null)
                    {
                        value = HttpUtility.UrlDecode(this.Page.Request.QueryString["Login"]);

                        // Need to reference .CommaSeparatedAccounts property before calling .Entities because 
                        // the collection seems to only get populated after that property is referenced.
                        string temp = this._InputForm.PeoplePicker.CommaSeparatedAccounts;
                        PickerEntity pickerEntity = new PickerEntity();
                        pickerEntity.Key = value;

                        try
                        {
                            this._InputForm.PeoplePicker.Entities.Add(pickerEntity);
                            this._InputForm.PeoplePicker.UpdateEntities(this._InputForm.PeoplePicker.Entities);
                        }
                        catch (Exception e)
                        {
                            allQSValuesValidForUserMode = false;
                            // If an error occurs we need to clear the entities collection otherwise
                            // the people picker will try and validate them again and fail... again.
                            this._InputForm.PeoplePicker.Entities.Clear();                             
                        }
                    }
                    else
                        allQSValuesValidForUserMode = false;

                    if (this.Page.Request.QueryString["Access"] != null)
                    {
                        value = HttpUtility.UrlDecode(this.Page.Request.QueryString["Access"]);
                        ListItem item = this._InputForm.RoleNameList.Items.FindByText(value);
                        if (item != null)
                        {
                            item.Selected = true;
                        }
                        else
                            throw new ApplicationException(Properties.Resources.Query_String_Invalid);
                    }
                    else
                        allQSValuesValidForUserMode = false;

                    if (this.Page.Request.QueryString["DownloadReport"] != null)
                    {
                        value = HttpUtility.UrlDecode(this.Page.Request.QueryString["DownloadReport"]);
                        if (value.ToLower().CompareTo("true") == 0)
                        {
                            // If all the required query string values have been specified and are valid, then flag that
                            // this web part is to respond to the user with an xml report file.
                            if ((ShowUserOrWebPermissions.Equals(AccessCheckerMode.User.ToString()) && allQSValuesValidForUserMode) ||
                                ShowUserOrWebPermissions.Equals(AccessCheckerMode.Web.ToString()))                            
                                this._DownloadReport = true;                            
                            else
                                throw new ApplicationException(Properties.Resources.Query_String_Invalid);
                        }
                    }
                }
                catch (ApplicationException appEx)
                {
                    _MessageArea.Text = appEx.Message;
                }
                catch (Exception e)
                {
                    throw new ApplicationException(Properties.Resources.Query_String_Processing_Failed);
                }
            }
        }

        /// <summary>
        /// This function is called when an error has occured, and the logging to file or eventlog requires 
        /// the security context to be elevated to the application pool account. The error is stored in the _Exception
        /// property.
        /// </summary>
        private void ElevatedLogError()
        {
            string resourcePath = GetClassResourceFilePath(SPWebPartManager.GetClassResourcePath(this._CurrentWeb, this.GetType()));
            if (_Exception != null)
                LogError(_Exception.Message, "AccessCheckerWebPart", resourcePath);
            else
                LogError(_ErrorMessage, "AccessCheckerWebPart", resourcePath);
        }

        /// <summary>
        /// Register client side scripts used for style and formatting of the TreeView and the Web Part as a whole.
        /// </summary>
        private void RegisterClientSideScripts()
        {
            String scriptName;
            String EmbeddedResourceFullName;
            Type cstype = this.GetType();

            // Get a ClientScriptManager reference from the Page class.
            ClientScriptManager scriptManager = Page.ClientScript;

            if (_SharepointPermissionsTreeView != null)
            {
                scriptName = "ACWP_ColourCodingScript_" + _SharepointPermissionsTreeView.ClientID;
                // Register javascript block which colour codes nodes in the TreeView.
                if (!scriptManager.IsClientScriptBlockRegistered(cstype, scriptName))
                {
                    scriptManager.RegisterClientScriptBlock(cstype, scriptName, this._SharepointPermissionsTreeView.GetColourCodingScript());
                }
            }

            // Register the style sheet on the current page.
            scriptName = "ACWP_StyleSheet";
            EmbeddedResourceFullName = "TomShirley.WebParts.AccessChecker.AccessCheckerStyle.css";
            if (!scriptManager.IsClientScriptBlockRegistered(cstype, scriptName))
            {
                StreamHelper.EnsureWebResourceValid(EmbeddedResourceFullName, this.GetType().Assembly, true);
                string jsURL = scriptManager.GetWebResourceUrl(cstype, EmbeddedResourceFullName);

                StringBuilder cstext = new StringBuilder();
                cstext.Append("<link href=\"" + jsURL + "\"");
                cstext.Append(" rel=\"stylesheet\"");
                cstext.Append(" type=\"text/css\" />");
                scriptManager.RegisterClientScriptBlock(cstype, scriptName, cstext.ToString(), false);
            }
        }

        /// <summary>
        /// Delete all nodes in the SPPermissionsTreeView control
        /// </summary>
        public void DeleteAllNodesInTree()
        {
            this._SharepointPermissionsTreeView.Nodes.Clear();
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Handle the click event of _InputForm.GenerateTreeviewForUserButton, which is used to build the SPPermissionsTreeView
        /// </summary>
        private void GenerateTreeviewForUserButton_Click(object sender, EventArgs e)
        {
            try
            {
                this._SharepointPermissionsTreeView.Nodes.Clear(); // Clear nodes so that the treeview gets re-populated on the next pre-render call               
            }
            catch (Exception ex)
            {
                _ErrorMessage += string.Format("{0} _GenerateUserReportButton_Click:\r\n{1}", Properties.Resources.Error_In, GetErrorMessage(ex));
            }
        }
        #endregion
    }
}
